/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.plc4x.java.bacnetip.readwrite;

import static org.apache.plc4x.java.spi.codegen.fields.FieldReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.fields.FieldWriterFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataReaderFactory.*;
import static org.apache.plc4x.java.spi.codegen.io.DataWriterFactory.*;
import static org.apache.plc4x.java.spi.generation.StaticHelper.*;

import java.math.BigInteger;
import java.time.*;
import java.util.*;
import org.apache.plc4x.java.api.exceptions.*;
import org.apache.plc4x.java.api.value.*;
import org.apache.plc4x.java.spi.codegen.*;
import org.apache.plc4x.java.spi.codegen.fields.*;
import org.apache.plc4x.java.spi.codegen.io.*;
import org.apache.plc4x.java.spi.generation.*;

// Code generated by code-generation. DO NOT EDIT.

public class BACnetTagPayloadUnsignedInteger implements Message {

  // Properties.
  protected final long actualLength;
  protected final Short valueUint8;
  protected final Integer valueUint16;
  protected final Integer valueUint24;
  protected final Long valueUint32;
  protected final Long valueUint40;
  protected final Long valueUint48;
  protected final Long valueUint56;
  protected final BigInteger valueUint64;

  public BACnetTagPayloadUnsignedInteger(
      long actualLength,
      Short valueUint8,
      Integer valueUint16,
      Integer valueUint24,
      Long valueUint32,
      Long valueUint40,
      Long valueUint48,
      Long valueUint56,
      BigInteger valueUint64) {
    super();
    this.actualLength = actualLength;
    this.valueUint8 = valueUint8;
    this.valueUint16 = valueUint16;
    this.valueUint24 = valueUint24;
    this.valueUint32 = valueUint32;
    this.valueUint40 = valueUint40;
    this.valueUint48 = valueUint48;
    this.valueUint56 = valueUint56;
    this.valueUint64 = valueUint64;
  }

  public long getActualLength() {
    return actualLength;
  }

  public Short getValueUint8() {
    return valueUint8;
  }

  public Integer getValueUint16() {
    return valueUint16;
  }

  public Integer getValueUint24() {
    return valueUint24;
  }

  public Long getValueUint32() {
    return valueUint32;
  }

  public Long getValueUint40() {
    return valueUint40;
  }

  public Long getValueUint48() {
    return valueUint48;
  }

  public Long getValueUint56() {
    return valueUint56;
  }

  public BigInteger getValueUint64() {
    return valueUint64;
  }

  public boolean getIsUint8() {
    return (boolean) ((actualLength) == (1));
  }

  public boolean getIsUint16() {
    return (boolean) ((actualLength) == (2));
  }

  public boolean getIsUint24() {
    return (boolean) ((actualLength) == (3));
  }

  public boolean getIsUint32() {
    return (boolean) ((actualLength) == (4));
  }

  public boolean getIsUint40() {
    return (boolean) ((actualLength) == (5));
  }

  public boolean getIsUint48() {
    return (boolean) ((actualLength) == (6));
  }

  public boolean getIsUint56() {
    return (boolean) ((actualLength) == (7));
  }

  public boolean getIsUint64() {
    return (boolean) ((actualLength) == (8));
  }

  public BigInteger getActualValue() {
    Object o =
        ((getIsUint8())
            ? getValueUint8()
            : (((getIsUint16())
                ? getValueUint16()
                : (((getIsUint24())
                    ? getValueUint24()
                    : (((getIsUint32())
                        ? getValueUint32()
                        : (((getIsUint40())
                            ? getValueUint40()
                            : (((getIsUint48())
                                ? getValueUint48()
                                : (((getIsUint56())
                                    ? getValueUint56()
                                    : getValueUint64())))))))))))));
    if (o instanceof BigInteger) return (BigInteger) o;
    return BigInteger.valueOf(((Number) o).longValue());
  }

  public void serialize(WriteBuffer writeBuffer) throws SerializationException {
    PositionAware positionAware = writeBuffer;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
    writeBuffer.pushContext("BACnetTagPayloadUnsignedInteger");

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isUint8 = getIsUint8();
    writeBuffer.writeVirtual("isUint8", isUint8);

    // Optional Field (valueUint8) (Can be skipped, if the value is null)
    writeOptionalField("valueUint8", valueUint8, writeUnsignedShort(writeBuffer, 8));

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isUint16 = getIsUint16();
    writeBuffer.writeVirtual("isUint16", isUint16);

    // Optional Field (valueUint16) (Can be skipped, if the value is null)
    writeOptionalField("valueUint16", valueUint16, writeUnsignedInt(writeBuffer, 16));

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isUint24 = getIsUint24();
    writeBuffer.writeVirtual("isUint24", isUint24);

    // Optional Field (valueUint24) (Can be skipped, if the value is null)
    writeOptionalField("valueUint24", valueUint24, writeUnsignedInt(writeBuffer, 24));

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isUint32 = getIsUint32();
    writeBuffer.writeVirtual("isUint32", isUint32);

    // Optional Field (valueUint32) (Can be skipped, if the value is null)
    writeOptionalField("valueUint32", valueUint32, writeUnsignedLong(writeBuffer, 32));

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isUint40 = getIsUint40();
    writeBuffer.writeVirtual("isUint40", isUint40);

    // Optional Field (valueUint40) (Can be skipped, if the value is null)
    writeOptionalField("valueUint40", valueUint40, writeUnsignedLong(writeBuffer, 40));

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isUint48 = getIsUint48();
    writeBuffer.writeVirtual("isUint48", isUint48);

    // Optional Field (valueUint48) (Can be skipped, if the value is null)
    writeOptionalField("valueUint48", valueUint48, writeUnsignedLong(writeBuffer, 48));

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isUint56 = getIsUint56();
    writeBuffer.writeVirtual("isUint56", isUint56);

    // Optional Field (valueUint56) (Can be skipped, if the value is null)
    writeOptionalField("valueUint56", valueUint56, writeUnsignedLong(writeBuffer, 56));

    // Virtual field (doesn't serialize anything, just makes the value available)
    boolean isUint64 = getIsUint64();
    writeBuffer.writeVirtual("isUint64", isUint64);

    // Optional Field (valueUint64) (Can be skipped, if the value is null)
    writeOptionalField("valueUint64", valueUint64, writeUnsignedBigInteger(writeBuffer, 64));

    // Virtual field (doesn't serialize anything, just makes the value available)
    BigInteger actualValue = getActualValue();
    writeBuffer.writeVirtual("actualValue", actualValue);

    writeBuffer.popContext("BACnetTagPayloadUnsignedInteger");
  }

  @Override
  public int getLengthInBytes() {
    return (int) Math.ceil((float) getLengthInBits() / 8.0);
  }

  @Override
  public int getLengthInBits() {
    int lengthInBits = 0;
    BACnetTagPayloadUnsignedInteger _value = this;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();

    // A virtual field doesn't have any in- or output.

    // Optional Field (valueUint8)
    if (valueUint8 != null) {
      lengthInBits += 8;
    }

    // A virtual field doesn't have any in- or output.

    // Optional Field (valueUint16)
    if (valueUint16 != null) {
      lengthInBits += 16;
    }

    // A virtual field doesn't have any in- or output.

    // Optional Field (valueUint24)
    if (valueUint24 != null) {
      lengthInBits += 24;
    }

    // A virtual field doesn't have any in- or output.

    // Optional Field (valueUint32)
    if (valueUint32 != null) {
      lengthInBits += 32;
    }

    // A virtual field doesn't have any in- or output.

    // Optional Field (valueUint40)
    if (valueUint40 != null) {
      lengthInBits += 40;
    }

    // A virtual field doesn't have any in- or output.

    // Optional Field (valueUint48)
    if (valueUint48 != null) {
      lengthInBits += 48;
    }

    // A virtual field doesn't have any in- or output.

    // Optional Field (valueUint56)
    if (valueUint56 != null) {
      lengthInBits += 56;
    }

    // A virtual field doesn't have any in- or output.

    // Optional Field (valueUint64)
    if (valueUint64 != null) {
      lengthInBits += 64;
    }

    // A virtual field doesn't have any in- or output.

    return lengthInBits;
  }

  public static BACnetTagPayloadUnsignedInteger staticParse(
      ReadBuffer readBuffer, Long actualLength) throws ParseException {
    readBuffer.pullContext("BACnetTagPayloadUnsignedInteger");
    PositionAware positionAware = readBuffer;
    boolean _lastItem = ThreadLocalHelper.lastItemThreadLocal.get();
    boolean isUint8 = readVirtualField("isUint8", boolean.class, (actualLength) == (1));

    Short valueUint8 = readOptionalField("valueUint8", readUnsignedShort(readBuffer, 8), isUint8);
    boolean isUint16 = readVirtualField("isUint16", boolean.class, (actualLength) == (2));

    Integer valueUint16 =
        readOptionalField("valueUint16", readUnsignedInt(readBuffer, 16), isUint16);
    boolean isUint24 = readVirtualField("isUint24", boolean.class, (actualLength) == (3));

    Integer valueUint24 =
        readOptionalField("valueUint24", readUnsignedInt(readBuffer, 24), isUint24);
    boolean isUint32 = readVirtualField("isUint32", boolean.class, (actualLength) == (4));

    Long valueUint32 = readOptionalField("valueUint32", readUnsignedLong(readBuffer, 32), isUint32);
    boolean isUint40 = readVirtualField("isUint40", boolean.class, (actualLength) == (5));

    Long valueUint40 = readOptionalField("valueUint40", readUnsignedLong(readBuffer, 40), isUint40);
    boolean isUint48 = readVirtualField("isUint48", boolean.class, (actualLength) == (6));

    Long valueUint48 = readOptionalField("valueUint48", readUnsignedLong(readBuffer, 48), isUint48);
    boolean isUint56 = readVirtualField("isUint56", boolean.class, (actualLength) == (7));

    Long valueUint56 = readOptionalField("valueUint56", readUnsignedLong(readBuffer, 56), isUint56);
    boolean isUint64 = readVirtualField("isUint64", boolean.class, (actualLength) == (8));

    BigInteger valueUint64 =
        readOptionalField("valueUint64", readUnsignedBigInteger(readBuffer, 64), isUint64);
    // Validation
    if (!((((((((isUint8) || (isUint16)) || (isUint24)) || (isUint32)) || (isUint40)) || (isUint48))
            || (isUint56))
        || (isUint64))) {
      throw new ParseValidationException("unmapped integer length");
    }
    BigInteger actualValue =
        readVirtualField(
            "actualValue",
            BigInteger.class,
            ((isUint8)
                ? valueUint8
                : (((isUint16)
                    ? valueUint16
                    : (((isUint24)
                        ? valueUint24
                        : (((isUint32)
                            ? valueUint32
                            : (((isUint40)
                                ? valueUint40
                                : (((isUint48)
                                    ? valueUint48
                                    : (((isUint56) ? valueUint56 : valueUint64))))))))))))));

    readBuffer.closeContext("BACnetTagPayloadUnsignedInteger");
    // Create the instance
    BACnetTagPayloadUnsignedInteger _bACnetTagPayloadUnsignedInteger;
    _bACnetTagPayloadUnsignedInteger =
        new BACnetTagPayloadUnsignedInteger(
            actualLength,
            valueUint8,
            valueUint16,
            valueUint24,
            valueUint32,
            valueUint40,
            valueUint48,
            valueUint56,
            valueUint64);
    return _bACnetTagPayloadUnsignedInteger;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (!(o instanceof BACnetTagPayloadUnsignedInteger)) {
      return false;
    }
    BACnetTagPayloadUnsignedInteger that = (BACnetTagPayloadUnsignedInteger) o;
    return (getActualLength() == that.getActualLength())
        && (getValueUint8() == that.getValueUint8())
        && (getValueUint16() == that.getValueUint16())
        && (getValueUint24() == that.getValueUint24())
        && (getValueUint32() == that.getValueUint32())
        && (getValueUint40() == that.getValueUint40())
        && (getValueUint48() == that.getValueUint48())
        && (getValueUint56() == that.getValueUint56())
        && (getValueUint64() == that.getValueUint64())
        && true;
  }

  @Override
  public int hashCode() {
    return Objects.hash(
        getActualLength(),
        getValueUint8(),
        getValueUint16(),
        getValueUint24(),
        getValueUint32(),
        getValueUint40(),
        getValueUint48(),
        getValueUint56(),
        getValueUint64());
  }

  @Override
  public String toString() {
    WriteBufferBoxBased writeBufferBoxBased = new WriteBufferBoxBased(true, true);
    try {
      writeBufferBoxBased.writeSerializable(this);
    } catch (SerializationException e) {
      throw new RuntimeException(e);
    }
    return "\n" + writeBufferBoxBased.getBox().toString() + "\n";
  }
}
